package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.wordmemorize.auth.StpKit;
import com.cskaoyan.wordmemorize.common.annotation.OperateLog;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.EmployeeConverter;
import com.cskaoyan.wordmemorize.dao.entity.EmployeeDO;
import com.cskaoyan.wordmemorize.dao.entity.EmployeeRoleDO;
import com.cskaoyan.wordmemorize.dao.entity.RoleDO;
import com.cskaoyan.wordmemorize.dao.mapper.EmployeeMapper;
import com.cskaoyan.wordmemorize.dao.mapper.EmployeeRoleMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RoleMapper;
import com.cskaoyan.wordmemorize.dto.admin.DeleteEmployeeRoleOperateDTO;
import com.cskaoyan.wordmemorize.dto.admin.EmployeeDTO;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.admin.RolePermissionDTO;
import com.cskaoyan.wordmemorize.request.EmployeeCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.service.EmployeeService;
import com.cskaoyan.wordmemorize.service.RolePermissionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 员工管理服务实现类
 */
@Service
@Slf4j
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, EmployeeDO> implements EmployeeService {

    @Autowired
    private EmployeeRoleMapper employeeRoleMapper;

    @Autowired
    private EmployeeConverter employeeConverter;

    @Autowired
    private RolePermissionService rolePermissionService;

    @Autowired
    private RoleMapper roleMapper;


    /**
     * 分页查询员工信息(后台账号权限管理-员工管理)
     *
     * @param request 分页请求参数
     * @return 员工信息分页数据
     */
    @Override
    public PageDTO<EmployeeDTO> getEmployeePage(PageRequest request) {
        // 构建查询条件
        LambdaQueryWrapper<EmployeeDO> queryWrapper = new LambdaQueryWrapper<>();

        // 如果有关键词，则添加模糊查询条件——员工姓名
        if (StringUtils.hasText(request.getKeyword())) {
            queryWrapper.like(EmployeeDO::getName, request.getKeyword());
        }

        // 分页查询
        // 构建分页对象的默认参数，默认从第一页开始，每页显示10条记录
        int pageNum = request.getPageNum() != null ? request.getPageNum() : 1;
        int count = request.getCount() != null ? request.getCount() : 10;
        Page<EmployeeDO> page = new Page<>(pageNum, count);
        page = page(page, queryWrapper);

        // 查询每个员工的角色
        List<EmployeeDO> records = page.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            for (EmployeeDO employee : records) {
                // 获取员工的角色ID列表
                List<Long> roleIds = getRoleIds(employee.getId());
                employee.setRoleIds(roleIds);

                // 获取员工的所有权限
                List<String> allPermissions = new ArrayList<>();

                // 遍历员工的每个角色，获取每个角色的权限
                if (!CollectionUtils.isEmpty(roleIds)) {
                    for (Long roleId : roleIds) {
                        try {
                            // 获取角色的权限信息
                            RolePermissionDTO rolePermissionDTO = rolePermissionService.getRolePermissionList(roleId);

                            // 将角色的权限添加到员工的权限列表中
                            if (rolePermissionDTO != null && !CollectionUtils.isEmpty(rolePermissionDTO.getAssignedPermissions())) {
                                allPermissions.addAll(rolePermissionDTO.getAssignedPermissions());
                            }
                        } catch (Exception e) {
                            // 如果获取权限时出错，继续处理下一个角色
                            log.error("Failed to get permissions for role: {}", roleId, e);
                        }
                    }
                }

                // 去除重复的权限
                List<String> distinctPermissions = allPermissions.stream().distinct().collect(Collectors.toList());
                employee.setPerms(distinctPermissions);
            }
        }

        // 转换为DTO
        return employeeConverter.employeePage2PageDTO(records, page.getTotal());
    }


    /**
     * 获取角色ID列表
     *
     * @param command 员工信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "员工", operateType = 1)
    public void addEmployee(EmployeeCommand command) {
        // 检查电话号码是否已存在
        LambdaQueryWrapper<EmployeeDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeDO::getPhoneNumber, command.getPhoneNumber());
        if (count(queryWrapper) > 0) {
            throw new BusinessException("该电话号码已被使用", 500);
        }

        // 转换为DO
        EmployeeDO employeeDO = employeeConverter.employeeCommand2DO(command);

        // 保存员工信息
        save(employeeDO);

        // 保存员工角色关系
        if (!CollectionUtils.isEmpty(command.getRoleIds())) {
            saveEmployeeRoles(employeeDO.getId(), command.getRoleIds());
        }
    }


    /**
     * 保存员工角色关系
     *
     * @param command 员工信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "员工", operateType = 2)
    public void updateEmployee(EmployeeCommand command) {
        // 检查员工是否存在
        EmployeeDO existEmployee = getById(command.getId());
        if (existEmployee == null) {
            throw new BusinessException("员工不存在", 500);
        }

        // 如果修改了电话号码，需要检查是否与其他员工冲突
        if (!existEmployee.getPhoneNumber().equals(command.getPhoneNumber())) {
            LambdaQueryWrapper<EmployeeDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(EmployeeDO::getPhoneNumber, command.getPhoneNumber())
                    .ne(EmployeeDO::getId, command.getId());
            if (count(queryWrapper) > 0) {
                throw new BusinessException(ResultCodeEnum.EMPLOYEE_DUPLICATION);
            }
        }

        // 转换为DO
        EmployeeDO employeeDO = employeeConverter.employeeCommand2DO(command);

        // 更新员工信息
        updateById(employeeDO);

        // 更新员工角色关系
        Long employeeId = Long.valueOf(command.getId());

        // 先删除原有角色关系
        LambdaQueryWrapper<EmployeeRoleDO> roleQueryWrapper = new LambdaQueryWrapper<>();
        roleQueryWrapper.eq(EmployeeRoleDO::getEmployeeId, employeeId);
        employeeRoleMapper.delete(roleQueryWrapper);

        // 保存新的角色关系
        if (!CollectionUtils.isEmpty(command.getRoleIds())) {
            saveEmployeeRoles(employeeId, command.getRoleIds());
        }
    }


    /**
     * 保存员工角色关系
     *
     * @param employeeId 员工ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "员工", operateType = 3)
    public void delete(Long employeeId) {
        // 检查员工是否存在
        EmployeeDO employeeDO = getById(employeeId);
        if (employeeDO == null) {
            throw new BusinessException("员工不存在", 500);
        }

        // 删除员工信息
        removeById(employeeId);

        // 删除员工角色关系
        LambdaQueryWrapper<EmployeeRoleDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeRoleDO::getEmployeeId, employeeId);
        employeeRoleMapper.delete(queryWrapper);
    }

    /**
     * 删除指定员工的角色
     *
     * @param employeeId 员工ID
     * @param roleId     角色ID
     * @return 操作日志DTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "员工角色", operateType = 3)
    public DeleteEmployeeRoleOperateDTO deleteRole(Long employeeId, Long roleId) {
        // 检查员工是否存在
        EmployeeDO employeeDO = getById(employeeId);
        if (employeeDO == null) {
            throw new BusinessException("员工不存在", 500);
        }

        // 删除员工角色关系
        LambdaQueryWrapper<EmployeeRoleDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeRoleDO::getEmployeeId, employeeId)
                .eq(EmployeeRoleDO::getRoleId, roleId);
        employeeRoleMapper.delete(queryWrapper);

        // 构建操作日志DTO
        DeleteEmployeeRoleOperateDTO operateDTO = new DeleteEmployeeRoleOperateDTO();
        operateDTO.setEmployeeId(employeeId);
        operateDTO.setRoleId(roleId.toString());
        operateDTO.setEmployeeName(employeeDO.getName());

        // 查询角色名称
        RoleDO roleDO = roleMapper.selectById(roleId);
        if (roleDO != null) {
            operateDTO.setRoleName(roleDO.getName());
        } else {
            operateDTO.setRoleName("");
        }

        return operateDTO;
    }

    /**
     * 更新登录信息
     *
     * @param employeeId 员工ID
     * @param ip         登录IP地址
     * @param time       登录时间
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "员工登录", operateType = 2)
    public void updateLoginInfo(Long employeeId, String ip, LocalDateTime time) {
        // 检查员工是否存在
        EmployeeDO employeeDO = getById(employeeId);
        if (employeeDO == null) {
            log.warn("尝试更新不存在的员工登录信息，employeeId: {}", employeeId);
            return;
        }

        // 使用 MyBatis-Plus 的通用更新方法
        EmployeeDO updateDO = new EmployeeDO();
        updateDO.setId(employeeId);
        updateDO.setLastLoginIp(ip);
        updateDO.setLastLoginTime(time);
        updateById(updateDO);

        // 作为备选方案，也可以使用自定义 SQL 方法更新登录信息
        // employeeMapper.updateLoginInfo(employeeId, ip, time);

        log.info("更新员工登录信息成功，employeeId: {}, ip: {}", employeeId, ip);
    }


    /**
     * 查询员工的角色ID列表
     *
     * @param employeeId 员工ID
     * @return 角色ID列表
     */
    private List<Long> getRoleIds(Long employeeId) {
        LambdaQueryWrapper<EmployeeRoleDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeRoleDO::getEmployeeId, employeeId);
        List<EmployeeRoleDO> employeeRoles = employeeRoleMapper.selectList(queryWrapper);

        if (CollectionUtils.isEmpty(employeeRoles)) {
            return new ArrayList<>();
        }

        return employeeRoles.stream()
                .map(EmployeeRoleDO::getRoleId)
                .collect(Collectors.toList());
    }


    /**
     * 保存员工角色关系
     *
     * @param employeeId 员工ID
     * @param roleIds    角色ID列表
     */
    private void saveEmployeeRoles(Long employeeId, List<String> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return;
        }

        for (String roleId : roleIds) {
            EmployeeRoleDO employeeRoleDO = new EmployeeRoleDO();
            employeeRoleDO.setEmployeeId(employeeId);
            employeeRoleDO.setRoleId(Long.valueOf(roleId));
            employeeRoleMapper.insert(employeeRoleDO);
        }
    }


    /**
     * 获取员工信息
     *
     * @return EmployeeDTO 员工信息
     */
    @Override
    public EmployeeDTO getEmployeeInfo() {
        // 获取当前登录用户ID
        String login = (String) StpKit.ADMIN.getLoginId();
        long loginId = Long.parseLong(login);

        // 获取员工基本信息
        EmployeeDO employeeDObyId = getById(loginId);
        if (employeeDObyId == null) {
            throw new BusinessException(ResultCodeEnum.FAIL);
        }

        EmployeeDTO employeeDTO = employeeConverter.employeeDO2DTO(employeeDObyId);

        // 获取员工角色
        List<Long> roleIds = getRoleIds(loginId);
        // 将 Long 类型转换为 String 类型
        List<String> roleIdStrings = roleIds.stream().map(String::valueOf).collect(Collectors.toList());
        employeeDTO.setRoleIds(roleIdStrings);

        // 获取员工权限
        List<String> permissions = getEmployeePermissions(loginId);
        employeeDTO.setPerms(permissions);

        return employeeDTO;
    }


    /**
     * 获取员工的权限列表
     *
     * @param loginId 登录用户id
     * @return 权限列表
     */
    @Override
    public List<String> getPermissionList(Object loginId) {
        if (loginId == null) {
            return new ArrayList<>();
        }

        long employeeId;

        if (loginId instanceof String) {
            employeeId = Long.parseLong((String) loginId);
        } else if (loginId instanceof Long) {
            employeeId = (Long) loginId;
        } else {
            return new ArrayList<>();
        }

        // 使用员工ID获取权限列表
        return getEmployeePermissions(employeeId);
    }


    /**
     * 获取员工的所有权限
     * 提取公共方法，供多个地方调用
     *
     * @param employeeId 员工ID
     * @return 权限列表
     */
    private List<String> getEmployeePermissions(Long employeeId) {
        // 获取员工的角色ID列表
        List<Long> roleIds = getRoleIds(employeeId);

        // 获取员工的所有权限
        List<String> allPermissions = new ArrayList<>();

        // 遍历员工的每个角色，获取每个角色的权限
        if (!CollectionUtils.isEmpty(roleIds)) {
            for (Long roleId : roleIds) {
                try {
                    // 获取角色的权限信息
                    RolePermissionDTO rolePermissionDTO = rolePermissionService.getRolePermissionList(roleId);

                    // 将角色的权限添加到员工的权限列表中
                    if (rolePermissionDTO != null && !CollectionUtils.isEmpty(rolePermissionDTO.getAssignedPermissions())) {
                        allPermissions.addAll(rolePermissionDTO.getAssignedPermissions());
                    }
                } catch (Exception e) {
                    log.error("获取角色权限失败，roleId: {}", roleId, e);
                }
            }
        }

        // 去除重复的权限
        return allPermissions.stream().distinct().collect(Collectors.toList());
    }
}
